package com.lonbon.threecameramaster

import android.graphics.ImageFormat
import android.graphics.SurfaceTexture
import android.hardware.Camera
import android.media.CamcorderProfile
import android.media.MediaRecorder
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.view.Surface
import android.view.SurfaceHolder
import androidx.appcompat.app.AppCompatActivity
import java.io.IOException
import java.util.concurrent.Executors

class CameraHelper(
    private val activity: AppCompatActivity,
    private var cameraId: Int,
    private var width: Int,
    private var height: Int,
) : Camera.PreviewCallback {
    private var surfaceHolder: SurfaceHolder? = null
    private var surfaceTexture: SurfaceTexture? = null
    private var mCamera: Camera? = null
    private var buffer: ByteArray? = null
    private var bytes: ByteArray? = null

    /**
     * 打开相机
     *
     * @param cameraId  0:HDMI  1：4K  2:1920X1080
     * 后摄 Camera.CameraInfo.CAMERA_FACING_BACK
     * 前摄 Camera.CameraInfo.CAMERA_FACING_FRONT
     */
    private fun open(cameraId: Int) {
        //获得camera对象
        mCamera = Camera.open(cameraId)
        mCamera?.let { camera ->
            //配置camera的属性
            val parameters = camera.parameters
            width = parameters?.previewSize!!.width
            height = parameters?.previewSize!!.height
            //设置预览数据格式为nv21
//            parameters.previewFormat = ImageFormat.NV21
//            //这是摄像头宽、高
//            setPreviewSize(parameters!!)
            // 设置摄像头 图像传感器的角度、方向
//            setPreviewOrientation(cameraId)
            camera.parameters = parameters
        }
    }

    /**
     * 切换摄像头
     */
    fun switchCamera() {
        val cameraId = if (cameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
            Camera.CameraInfo.CAMERA_FACING_FRONT
        } else {
            Camera.CameraInfo.CAMERA_FACING_BACK
        }
        switchCamera(cameraId)
    }

    /**
     * 切换摄像头
     * @param cameraId 指定摄像头ID
     */
    fun switchCamera(cameraId: Int) {
        this.cameraId = cameraId
        previewAlign()
    }

    private fun previewAlign() {
        stopPreview()
        if (surfaceHolder != null) {
            startPreview(surfaceHolder!!)
        } else {
            startPreview(surfaceTexture!!)
        }
    }

    /**
     * 停止预览
     */
    fun stopPreview() {
        if (mCamera != null) {
            mCamera?.setPreviewCallback(null)
            mCamera?.stopPreview()
            mCamera?.release()
            mCamera = null
        }
    }

    /**
     * 开始预览
     */
    fun startPreview(surfaceHolder: SurfaceHolder) {
        try {
            open(cameraId)
        } catch (e:Exception){
            Log.d(TAG,"fail:${e.printStackTrace()}")
        }

        this.surfaceHolder = surfaceHolder
        buffer = ByteArray(width * height * 3 / 2)
        bytes = ByteArray(buffer!!.size)
        //数据缓存区
        mCamera?.addCallbackBuffer(buffer)
        mCamera?.setPreviewCallbackWithBuffer(this)
        //设置预览画面
        mCamera?.setPreviewDisplay(surfaceHolder)
        mCamera?.startPreview()
    }

    fun startPreview(surfaceTexture: SurfaceTexture) {
        open(cameraId)
        this.surfaceTexture = surfaceTexture
        buffer = ByteArray(width * height * 3 / 2)
        bytes = ByteArray(buffer!!.size)
        //数据缓存区
        mCamera?.addCallbackBuffer(buffer)
        mCamera?.setPreviewCallbackWithBuffer(this)
        //设置预览画面
        mCamera?.setPreviewTexture(surfaceTexture)
        mCamera?.startPreview()
    }

    override fun onPreviewFrame(data: ByteArray, camera: Camera?) {
        onPreviewListener?.onPreviewFrame(data, camera,width,height)
        camera!!.addCallbackBuffer(data)
    }

    private fun setPreviewSize(parameters: Camera.Parameters) {
        //获取摄像头支持的宽、高
        val supportedPreviewSizes = parameters.supportedPreviewSizes
        var size = supportedPreviewSizes[0]
        Log.d(TAG, "Camera支持: " + size.width + "x" + size.height)
        //选择一个与设置的差距最小的支持分辨率
        var m: Int = Math.abs(size.height * size.width - width * height)
        supportedPreviewSizes.removeAt(0)
        val iterator: Iterator<Camera.Size> = supportedPreviewSizes.iterator()
        //遍历
        while (iterator.hasNext()) {
            val next = iterator.next()
            Log.d(TAG, "支持 " + next.width + "x" + next.height)
            val n: Int = Math.abs(next.height * next.width - width * height)
            if (n < m) {
                m = n
                size = next
            }
        }
        width = size.width
        height = size.height
        parameters.setPreviewSize(width, height)
        Log.d(TAG, "预览分辨率 width:" + size.width + " height:" + size.height)
    }

    private val mOnChangedSizeListener: OnChangedSizeListener? = null

    private fun setPreviewOrientation(cameraId: Int) {
        val info = Camera.CameraInfo()
        Camera.getCameraInfo(cameraId, info)
        val rotation = activity.windowManager.defaultDisplay.rotation
        var degrees = 0
        when (rotation) {
            Surface.ROTATION_0 -> {
                degrees = 0
                mOnChangedSizeListener?.onChanged(height, width)
            }

            Surface.ROTATION_90 -> {
                degrees = 90
                mOnChangedSizeListener?.onChanged(width, height)
            }

            Surface.ROTATION_180 -> {
                degrees = 180
                mOnChangedSizeListener?.onChanged(height, width)
            }

            Surface.ROTATION_270 -> {
                degrees = 270
                mOnChangedSizeListener?.onChanged(width, height)
            }
        }
        var result: Int
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360
            result = (360 - result) % 360 // compensate the mirror
        } else { // back-facing
            result = (info.orientation - degrees + 360) % 360
        }
        //设置角度, 参考源码注释
        mCamera!!.setDisplayOrientation(result)
    }

    interface OnChangedSizeListener {
        fun onChanged(width: Int, height: Int)
    }

    interface OnPreviewListener {
        fun onPreviewFrame(data: ByteArray, camera: Camera?,width: Int,height: Int)
    }

    private var onPreviewListener: OnPreviewListener? = null

    /**
     * 设置预览监听
     */
    fun setOnPreviewListener(listener: OnPreviewListener) {
        this.onPreviewListener = listener
    }

    companion object {
        private const val TAG = "CAMERA_HELPER"
    }
}
